/*
 * KKNode.cpp
 *
 *  Created on: 2013-9-15
 *      Author: wanghua
 */

#include "KKNode.h"
#include "KKText.h"
#include "KKSprite.h"
#include "KKLayer.h"
#include "KKGridView.h"
#include "XmlUtils.h"
#include "KKDirector.h"
#include "KKLayout.h"
#include <cstring>
#include <iostream>

USING_NS_CC;

KKNode::KKNode() {

	this->m_GestureDirector = KKGestureDirector::create(this);

	this->m_properties = new KKPropertiesDictionary();
	this->m_events = new KKEventDictionary();
	this->m_objects = new KKNodeArray();
	this->m_nodeVertexs = NULL;
	this->m_isSupportMultiTouch = true;
	this->m_isTouchable = false;
	this->m_isChildTouchable = false;
	this->m_isDragable = false;
	this->m_isMovable = false;
	this->m_isRotatable = false;
	this->m_isZoomable = false;
	this->m_isLoaded = false;
	this->m_isUseLocalTouch = true;
	this->m_ccNode = NULL;
	this->m_kkParent = NULL;
	this->m_bgColor = NULL;
	this->m_shadowEffectColor = NULL;
	this->m_isItemTouchable = false;
	this->m_isEnable = true;
	this->m_width = 0;
	this->m_height = 0;
	this->m_minX = 0;
	this->m_minY = 0;
	this->m_selected = false;
	this->m_isSoundEffect = false;
	this->m_clickEffect = KKEFFECT_NONE;
	this->m_isMoved = false;
	this->m_layout = NULL;
	this->m_element = NULL;
	this->m_document = NULL;
	this->m_type = KKTYPE_NORMAL;
	this->m_hasHotArea = false;

	this->m_used = false;

	this->m_zOrder = 0;

	this->m_widthType = fix;
	this->m_heightType = fix;

	this->m_layoutX = 0;
	this->m_layoutY = 0;

	this->m_friction = 0;
	this->m_restitution = 0;
	this->m_density = 1;
	this->m_body = NULL;
	this->m_isSensor = false;
}

KKNode::~KKNode() {
	CC_SAFE_DELETE(m_GestureDirector);
	CC_SAFE_DELETE(m_properties);
	CC_SAFE_DELETE(m_events);
	CC_SAFE_DELETE(m_objects);
	CC_SAFE_DELETE(m_nodeVertexs);
	CC_SAFE_DELETE(m_layout);

	this->m_isTouchable = false;
	this->m_kkParent = NULL;

	CC_SAFE_DELETE(m_document);
}

void KKNode::runStoryboard(const char* storyboardName) {
	KKScene* curScene = KKDirector::shareDirector()->getCurrentScene();
	KKStoryboard* storyboard = curScene->storyboardNamed(storyboardName);

	if (storyboard) {

		KKAnimationArray* animations = storyboard->getAnimations();

		KKAnimationArray::CCMutableArrayIterator it = animations->begin();

		KKAnimation* animation = NULL;

		CCNode* target = NULL;

		bool notFoundAnim = true;

		while (it != animations->end()) {

			animation = (KKAnimation*) (*it);

			if (m_name == animation->getTargetName()) {
				target = dynamic_cast<CCNode*>(this);
			} else {
				target = dynamic_cast<CCNode*>(this->nodeNamed(
						animation->getTargetName()));
			}

			if (target) {
				notFoundAnim = false;
				animation->start(target);
			}

			it++;
		}

		if (notFoundAnim && animation != NULL) {
			target = dynamic_cast<CCNode*>(this);
			if (target) {
				animation->start(target);
			}
		}
	}
}
bool KKNode::loadNode() {

	if (this->m_isLoaded) {
		return true;
	}

	if (m_element) {
		this->initLayoutFromXml(m_element, m_kkParent);
		this->m_isLoaded = initDelayInfoWithXml(this->m_element);
	}

	measure();
	layout();

	return this->m_isLoaded;
}

void KKNode::unloadNode() {
	this->m_isLoaded = false;

	this->m_ccNode->removeAllChildrenWithCleanup(true);
	this->m_objects->removeAllObjects();

	CCNode* node = dynamic_cast<CCNode*>(this);

	node->removeChildByTag(BG_COLOR_TAG, true);
	node->removeChildByTag(BG_IMAGE_TAG, true);
	node->removeChildByTag(SHADOW_COLOR_TAG, true);

	CC_SAFE_DELETE(m_layout);

	CCTextureCache::sharedTextureCache()->removeUnusedTextures();
}

bool KKNode::checkAutoLoad() {

	const char* visiable = m_element->Attribute("visiable");

	if (visiable && strcmp("false", m_element->Attribute("visiable")) == 0) {
		return false;
	}

	return true;
}

bool KKNode::initWithXml(TiXmlElement* element, KKNode* parent) {
	this->m_element = element;

	if (this->initCommonInfoWithXml(element, parent)) {

		if (this->checkAutoLoad()) {

			m_isLoaded = loadNode();

			return m_isLoaded;
		}

		return true;
	}

	return false;
}

#define MEASURE_BEFORE 0

void KKNode::initLayoutFromXml(TiXmlElement* element, KKNode* parent) {

	const char* wType = element->Attribute("w-type");

	if (wType) {
		if (strcmp(wType, "fill_parent") == 0) {
			this->m_widthType = fill_parent;
		} else if (strcmp(wType, "wrap_content") == 0) {
			this->m_widthType = wrap_content;
		}
	}

	const char* hType = element->Attribute("h-type");

	if (hType) {
		if (strcmp(hType, "fill_parent") == 0) {
			this->m_heightType = fill_parent;
		} else if (strcmp(hType, "wrap_content") == 0) {
			this->m_heightType = wrap_content;
		}
	}

	TiXmlElement* layoutElement = element->FirstChildElement("layout");

	if (layoutElement) {
		this->m_layout = KKLayoutParser::parseFromXml(layoutElement);
	}

#if MEASURE_BEFORE>0
	KKLayout* parentLayout = NULL;

	float measureWidth = 0;
	float measureHeight = 0;

	if (parent) {
		parentLayout = parent->getLayout();
		measureWidth = parent->getWidth();
		measureHeight = parent->getHeight();
	} else {
		const CCSize& size = CCDirector::sharedDirector()->getWinSize();
		measureWidth = size.width;
		measureHeight = size.height;
	}

	if (!parentLayout) {
		parentLayout = new AbsLayout();
		parentLayout->retain();
		parentLayout->autorelease();
	}

	parentLayout->measureChild(
			this,
			measureWidth - parentLayout->getPaddingLeft()
			- parentLayout->getPaddingRight(),
			measureHeight - parentLayout->getPaddingBottom()
			- parentLayout->getPaddingTop());

#endif

}

bool KKNode::initCommonInfoWithXml(TiXmlElement* element, KKNode* parent) {

	CCNode* node = dynamic_cast<CCNode*>(this);

	if (m_ccNode == NULL) {
		m_ccNode = node;
	}

	this->m_name = element->Attribute("name");

	const char* image = element->Attribute("image");
	if (image) {
		this->m_image = image;
	} else {
		this->m_image.clear();
	}

	image = element->Attribute("hotImage");
	if (image) {
		this->m_hotImage = image;
	} else {
		this->m_hotImage.clear();
	}

	image = element->Attribute("disableImage");
	if (image) {
		this->m_disableImage = image;
	} else {
		this->m_disableImage.clear();
	}

	this->m_kkParent = parent;

	int x = atoi(element->Attribute("x")) / CC_CONTENT_SCALE_FACTOR();
	int y = atoi(element->Attribute("y")) / CC_CONTENT_SCALE_FACTOR();
	float width = atof(element->Attribute("width")) / CC_CONTENT_SCALE_FACTOR();
	float height = atof(
			element->Attribute("height")) / CC_CONTENT_SCALE_FACTOR();

	CCSprite* parentSprite = dynamic_cast<CCSprite*>(m_kkParent);

	if (parentSprite) {
		width *= 1 / parentSprite->getScaleX();
		height *= 1 / parentSprite->getScaleY();
		x = (int) (x / parentSprite->getScaleX());
		y = (int) (y / parentSprite->getScaleY());
	}

	this->m_x = int(x);
	this->m_y = int(y);

	this->m_width = abs(int(width));
	this->m_height = abs(int(height));

	initLayoutFromXml(element, parent);

	if (element->Attribute("anchorX")) {
		float anchorX = atof(element->Attribute("anchorX"));
		float anchorY = atof(element->Attribute("anchorY"));
		node->setAnchorPoint(ccp(anchorX, anchorY));
	}

	int angle = 0;

	if (element->Attribute("angle")) {
		angle = atoi(element->Attribute("angle"));
	}

	float alpha = 255;

	if (element->Attribute("alpha")) {
		alpha = atof(element->Attribute("alpha"));
	}

	const char* visiable = element->Attribute("visiable");

	m_maxX = this->m_width;
	m_maxY = this->m_height;

	if (node->getContentSize().width > 0) {
		node->setScaleX(this->m_width / node->getContentSize().width);
		node->setScaleY(this->m_height / node->getContentSize().height);
	} else {
		node->setContentSize(CCSize(this->m_width, this->m_height));
	}

	const char* scaleX = element->Attribute("scalex");

	if (scaleX) {
		node->setScaleX(atof(scaleX));
	} else if (width < 0) {
		node->setScaleX(-node->getScaleX());
	}

	const char* scaleY = element->Attribute("scaley");

	if (scaleY) {
		node->setScaleY(atof(scaleY));
	} else if (height < 0) {
		node->setScaleY(-node->getScaleY());
	}

	node->setRotation(angle);

	if (visiable) {
		node->setVisible(strcmp(visiable, "false"));
	} else if (!node->isVisible()) {
		node->setVisible(true);
	}

	node->setPosition(ccp(x, y));

	if (element->Attribute("id")) {
		this->m_id = atoi(element->Attribute("id"));
	}

	node->setTag(m_id);

	const char* type = element->Attribute("type");

	if (type) {
		string nodeType = type;
		if (nodeType == "button") {
			this->m_type = KKTYPE_BUTTON;
		} else if (nodeType == "dynamic") {
			this->m_type = KKTYPE_DYNAMIC_BODY;
		} else if (nodeType == "fix") {
			this->m_type = KKTYPE_STATIC_BODY;
		} else {
			this->m_type = KKTYPE_NORMAL;
		}
	} else {
		this->m_type = KKTYPE_NORMAL;
	}

	const char* clickEffect = element->Attribute("click-effect");

	if (clickEffect) {
		string effect = clickEffect;
		if (effect == "zoom_in") {
			m_clickEffect = KKEFFECT_ZOOMIN;
		} else if (effect == "zoom_out") {
			m_clickEffect = KKEFFECT_ZOOMOUT;
		} else if (effect == "shadow") {
			m_clickEffect = KKEFFECT_SHADOW;
		}
	}

	getProperties()->removeAllObjects();

	TiXmlElement* propertyElment = element->FirstChildElement("property");

	while (propertyElment != NULL) {

		getProperties()->setObject(
				new CCString(propertyElment->Attribute("value")),
				propertyElment->Attribute("name"));

		propertyElment = propertyElment->NextSiblingElement("property");

	}

	TiXmlElement* eventElment = element->FirstChildElement("event");

	getEvents()->removeAllObjects();

	while (eventElment != NULL) {

		KKEvent* event = KKEvent::eventWithXml(eventElment);

		if (event) {

			getEvents()->setObject(event, event->getName());
		}

		eventElment = eventElment->NextSiblingElement("event");

	}

	TiXmlElement* vertexesElment = element->FirstChildElement("vertexes");

	if (m_nodeVertexs) {
		m_nodeVertexs->removeAllObjects();
	}

	KKNodeVertexes* vertexs = NULL;

	while (vertexesElment) {

		KKPoint* vertex = NULL;

		vertexs = new KKNodeVertexes();

		vertexs->setName(vertexesElment->Attribute("name"));
		vertexs->setType(
				XmlUtils::getStringAttr(vertexesElment, "type", "poly"));

		TiXmlElement* vertexElment = vertexesElment->FirstChildElement("v");

		while (vertexElment != NULL) {

			vertex = new KKPoint(atof(vertexElment->Attribute("x")),
					atof(vertexElment->Attribute("y")));

			vertex->width = XmlUtils::getFloatAttr(vertexElment, "width", 2);

			vertex->retain();

			vertexs->getVertexs()->addObject(vertex);

			vertexElment = vertexElment->NextSiblingElement("v");
		}

		if (vertexs->getVertexs()->count() < 2) {

			vertexs->getVertexs()->removeAllObjects();

			CC_SAFE_DELETE(vertexs);

		} else {
			if (!m_nodeVertexs) {
				m_nodeVertexs = new KKNodeVertexesArray();
			}
			m_nodeVertexs->addObject(vertexs);
		}

		vertexesElment = vertexesElment->NextSiblingElement("vertexes");

	}
	this->m_isSoundEffect = XmlUtils::getBoolAttr(element, "effect", false);
	this->m_isEnable = XmlUtils::getBoolAttr(element, "enabled", true);
	this->m_isTouchable = XmlUtils::getBoolAttr(element, "clickable", false);
	this->m_isMovable = XmlUtils::getBoolAttr(element, "movable", false);
	this->m_isRotatable = XmlUtils::getBoolAttr(element, "rotatable", false);
	this->m_isZoomable = XmlUtils::getBoolAttr(element, "zoomable", false);
	this->m_isDragable = XmlUtils::getBoolAttr(element, "dragable",
			this->m_isMovable || m_isRotatable);

	this->m_hasHotArea = XmlUtils::getBoolAttr(element, "hotarea", false);

	this->m_isItemTouchable = XmlUtils::getBoolAttr(element, "itemclickable",
			false);

	this->m_isSupportMultiTouch = XmlUtils::getBoolAttr(element, "multitouch",
			m_isSupportMultiTouch);

	this->touchHolder.removeAllObjects();

	CCRGBAProtocol* sprite = dynamic_cast<CCRGBAProtocol*>(node);

	if (sprite) {
		sprite->setOpacity(alpha);
	}

	CCBlendProtocol* blendProtocol = dynamic_cast<CCBlendProtocol*>(node);

	if (blendProtocol) {
		//blendProtocol->setBlendFunc({});
	}

	this->m_density = XmlUtils::getFloatAttr(element, "density", 0);
	this->m_friction = XmlUtils::getFloatAttr(element, "friction", 0);
	this->m_restitution = XmlUtils::getFloatAttr(element, "restitution", 0);

	this->m_velocityX = XmlUtils::getFloatAttr(element, "velocityX", 0);
	this->m_velocityY = XmlUtils::getFloatAttr(element, "velocityY", 0);

	this->m_isSensor = XmlUtils::getBoolAttr(element, "sensor", false);

	this->m_zOrder = XmlUtils::getIntAttr(element, "z-order", 0);

	m_element = element;

	return true;
}

bool KKNode::initDelayInfoWithXml(TiXmlElement* element) {

	CCNode* node = dynamic_cast<CCNode*>(this);

	if (m_ccNode == NULL) {
		m_ccNode = node;
	}

	const char* bgAlpha = element->Attribute("bgAlpha");

	if (bgAlpha) {

		ccColor3B bgRgb = strToColor3(
				XmlUtils::getStringAttr(element, "bg", "ffffff"));
		ccColor4B bgColor = { bgRgb.r, bgRgb.g, bgRgb.b, atoi(bgAlpha) };

		CCNode* node = this->convertToCCNode();

		m_bgColor = CCLayerColor::create(bgColor, node->getContentSize().width,
				node->getContentSize().height);

		node->addChild(m_bgColor, BG_COLOR_ZORDER, BG_COLOR_TAG);
	}

	if (m_clickEffect == KKEFFECT_SHADOW) {

		ccColor4B bgColor = { 0, 0, 0, 80 };

		m_shadowEffectColor = CCLayerColor::create(bgColor,
				node->getContentSize().width, node->getContentSize().height);
		m_shadowEffectColor->setVisible(false);
		node->addChild(m_shadowEffectColor, SHADOW_COLOR_ZORDER,
				SHADOW_COLOR_TAG);
	}

	TiXmlElement * childElement = element->FirstChildElement("object");

	m_minX = 0;
	m_minY = 0;
	m_maxX = m_width;
	m_maxY = m_height;

	int zOrder = 0;

	while (childElement != NULL) {
		KKNode * object = KKNodeParser::parseFromXml(childElement, this);
		if (object) {

			m_isChildTouchable = m_isChildTouchable || object->getIsTouchable()
					|| object->getIsChildTouchable();

			if (m_kkParent != NULL && m_isChildTouchable) {
				m_kkParent->setIsChildTouchable(m_isChildTouchable);
			}

			/*if(zOrder>object->getZOrder()&&object->getZOrder()==0){
			 object->setZOrder(++zOrder);
			 }*/

			this->addNode(object, object->getZOrder());

			zOrder = object->getZOrder();

		}

		childElement = childElement->NextSiblingElement("object");
	}

	return true;
}

void KKNode::saveToXml(TiXmlElement* element) {

	CCNode* node = dynamic_cast<CCNode*>(this);

	element->SetAttribute("id", m_id);
	element->SetAttribute("name", m_name.c_str());

	if (!m_image.empty()) {
		element->SetAttribute("image", m_image.c_str());
	}

	if (!m_hotImage.empty()) {
		element->SetAttribute("hotImage", m_hotImage.c_str());
	}

	if (!m_disableImage.empty()) {
		element->SetAttribute("disableImage", m_disableImage.c_str());
	}

	element->SetDoubleAttribute("x", node->getPositionX());
	element->SetDoubleAttribute("y", node->getPositionY());

	element->SetDoubleAttribute("width",
			node->getContentSize().width * node->getScaleX());
	element->SetDoubleAttribute("height",
			node->getContentSize().height * node->getScaleY());
	element->SetDoubleAttribute("anchorX", node->getAnchorPoint().x);
	element->SetDoubleAttribute("anchorY", node->getAnchorPoint().y);
	element->SetDoubleAttribute("angle", node->getRotation());

	CCRGBAProtocol* rgba = dynamic_cast<CCRGBAProtocol*>(this);

	if (rgba) {
		element->SetAttribute("alpha", rgba->getOpacity());
	}

	element->SetAttribute("clickable", m_isTouchable ? "true" : "false");
	element->SetAttribute("dragable", m_isDragable ? "true" : "false");
	element->SetAttribute("enabled", m_isEnable ? "true" : "false");

	vector<string> propertyNames = this->m_properties->allKeys();

	for (unsigned int i = 0; i < propertyNames.size(); i++) {
		TiXmlElement* propertyElement = new TiXmlElement("property");
		propertyElement->SetAttribute("name", propertyNames[i].c_str());
		propertyElement->SetAttribute("value",
				this->m_properties->objectForKey(propertyNames[i])->getCString());

		element->LinkEndChild(propertyElement);
	}

	vector<string> eventNames = this->m_events->allKeys();

	for (unsigned int i = 0; i < eventNames.size(); i++) {
		TiXmlElement* eventElement = new TiXmlElement("event");
		eventElement->SetAttribute("name", eventNames[i].c_str());
		KKEvent* event = this->m_events->objectForKey(eventNames[i]);
		KKEventActionArray* actions = event->getActions();

		for (unsigned int j = 0; j < actions->count(); j++) {
			TiXmlElement* actionElement = new TiXmlElement("action");
			KKEventAction* action = actions->getObjectAtIndex(j);

			actionElement->SetAttribute("id", action->getTargetId());
			actionElement->SetAttribute("target", action->getTarget());
			actionElement->SetAttribute("action", action->getAction());

			switch (action->getTargetType()) {
			case TARGET_SCENE:
				actionElement->SetAttribute("targetType", "scene");
				break;
			case TARGET_LAYER:
				actionElement->SetAttribute("targetType", "layer");
				break;
			case TARGET_SPRITE:
				actionElement->SetAttribute("targetType", "sprite");
				break;
			case TARGET_STORYBOARD:
				actionElement->SetAttribute("targetType", "anim");
				break;
			case TARGET_SOUND:
				actionElement->SetAttribute("targetType", "sound");
				break;

			}

			switch (action->getActionType()) {
			case ACTION_SCRIPT:
				actionElement->SetAttribute("actionType", "script");
				break;
			case ACTION_STATUS:
				actionElement->SetAttribute("actionType", "status");
				break;
			case ACTION_SET_PROPERTY:
				actionElement->SetAttribute("actionType", "property");
				break;
			case ACTION_SOUND:
				actionElement->SetAttribute("actionType", "sound");
				break;
			case ACTION_ANIM:
				actionElement->SetAttribute("actionType", "anim");
				break;
			default:
				break;

			}

			eventElement->LinkEndChild(actionElement);
		}

		element->LinkEndChild(eventElement);
	}

	KKNode* child = NULL;

	for (unsigned int i = 0; i < m_objects->count(); i++) {
		child = m_objects->getObjectAtIndex(i);
		if (child) {
			TiXmlElement* childElement = new TiXmlElement("object");

			child->saveToXml(childElement);
			element->LinkEndChild(childElement);
		}
	}
}

KKNode* KKNode::cloneNode(bool forceUpdate) {
	TiXmlElement* element = m_element;
	if (forceUpdate || !element) {
		element = new TiXmlElement("object");
		this->saveToXml(element);
	}
	KKNode* newNode = KKNodeParser::parseFromXml(element, this->m_kkParent);

	return newNode;
}

void KKNode::initWithNode(KKNode* node) {
	TiXmlElement* element = new TiXmlElement("object");
	node->saveToXml(element);
	this->initWithXml(element, this->getKKParent());
}

void KKNode::resetNode(bool reload, bool stopAction) {

	CCNode* node = dynamic_cast<CCNode*>(this);

	if (stopAction) {
		node->stopAllActions();
	}

	this->performEvent("onreset", NULL);
	this->performEvent("oninit", NULL);

	const float& width = m_width;
	const float& height = m_height;
	const float& x = m_x;
	const float& y = m_y;

	if (reload) {
		this->unloadNode();

		if (m_element) {
			this->initWithXml(m_element, m_kkParent);
		}

	} else {

		if (m_element) {

			this->initCommonInfoWithXml(m_element, m_kkParent);
		}

		KKNode* child = NULL;
		for (unsigned int i = 0; i < m_objects->count(); i++) {
			child = m_objects->getObjectAtIndex(i);
			if (child) {
				child->resetNode(reload, stopAction);
			}
		}

	}

	this->resize(width, height);
	this->convertToCCNode()->setPosition(x, y);
	m_x = x;
	m_y = y;
}

void KKNode::pauseNode() {
	KKNode* child = NULL;

	for (unsigned int i = 0; i < m_objects->count(); i++) {
		child = m_objects->getObjectAtIndex(i);
		if (child) {
			child->pauseNode();
		}
	}

	CCNode* node = dynamic_cast<CCNode*>(this);
	if (node) {
		CCDirector::sharedDirector()->getActionManager()->pauseTarget(node);
		CCObject * childNode = NULL;

		CCARRAY_FOREACH (node->getChildren(),childNode) {
			CCDirector::sharedDirector()->getActionManager()->pauseTarget(
					childNode);
		}
	}
}

void KKNode::resumeNode() {
	KKNode* child = NULL;

	for (unsigned int i = 0; i < m_objects->count(); i++) {
		child = m_objects->getObjectAtIndex(i);
		if (child) {
			child->resumeNode();
		}
	}

	CCNode* node = dynamic_cast<CCNode*>(this);
	if (node) {
		CCDirector::sharedDirector()->getActionManager()->resumeTarget(node);

		CCObject* childNode = NULL;

		CCARRAY_FOREACH (node->getChildren(),childNode) {
			CCDirector::sharedDirector()->getActionManager()->resumeTarget(
					childNode);
		}
	}
}

void KKNode::onInit() {

	this->performEvent("oninit", NULL);

	KKNode* child = NULL;

	for (unsigned int i = 0; i < m_objects->count(); i++) {
		child = m_objects->getObjectAtIndex(i);
		if (child) {
			child->onInit();
		}
	}

}

bool KKNode::getIsChildTouchable(void) {
	return this->m_isChildTouchable;
}

void KKNode::setIsChildTouchable(bool isChildTouchable) {
	this->m_isChildTouchable = isChildTouchable;
	if (isChildTouchable && m_kkParent && !m_kkParent->getIsChildTouchable()) {
		m_kkParent->setIsChildTouchable(isChildTouchable);
	}
}

bool KKNode::getIsTouchable(void) {
	return this->m_isTouchable;
}

void KKNode::setIsTouchable(bool isTouchable) {
	this->m_isTouchable = isTouchable;

	if (isTouchable && m_kkParent && !m_kkParent->getIsChildTouchable()) {
		m_kkParent->setIsChildTouchable(isTouchable);
	}
}

void KKNode::setAnchorPointNotChangePosition(const CCPoint& anchorPoint) {

	CCNode* node = dynamic_cast<CCNode*>(this);

	float dx = 0;
	float dy = 0;

	if (node->getParent()) {

		CCPoint anchorPoint1 =
		CCPointApplyAffineTransform(
		ccp(
				node->getAnchorPoint().x
				* node->getContentSize().width,
				node->getAnchorPoint().y
				* node->getContentSize().height),
		node->nodeToParentTransform());

		CCPoint anchorPoint2 = CCPointApplyAffineTransform(
		ccp(anchorPoint.x * node->getContentSize().width,
				anchorPoint.y * node->getContentSize().height),
		node->nodeToParentTransform());

		dx = anchorPoint1.x - anchorPoint2.x;
		dy = anchorPoint1.y - anchorPoint2.y;

	}

	node->setAnchorPoint(anchorPoint);

	if (dx != 0 || dy != 0) {
		node->setPosition(node->getPositionX() - dx, node->getPositionY() - dy);
	}
}

float KKNode::getScaledWidth() {
	CCNode* node = dynamic_cast<CCNode*>(this);

	return node->getContentSize().width * node->getScaleX();
}

float KKNode::getScaledHeight() {
	CCNode* node = dynamic_cast<CCNode*>(this);

	return node->getContentSize().height * node->getScaleY();
}

int KKNode::getIntProperty(string key, int defaultValue) {
	CCString* value = m_properties->objectForKey(key);
	if (value) {
		return value->intValue();
	}

	return defaultValue;
}

float KKNode::getFloatProperty(string key, float defaultValue) {
	CCString* value = m_properties->objectForKey(key);
	if (value) {
		return value->floatValue();
	}

	return defaultValue;
}

bool KKNode::getBooleanProperty(string key, bool defaultValue) {
	CCString* value = m_properties->objectForKey(key);
	if (value) {
		return value->compare("true") == 0;
	}

	return defaultValue;
}

string KKNode::getStringProperty(string key, const char* defaultValue) {
	CCString* value = m_properties->objectForKey(key);
	if (value) {
		return value->m_sString;
	}

	return defaultValue;
}

void KKNode::setProperty(string key, int newValue) {
	CCString* value = new CCString(intToString(newValue));

	m_properties->removeObjectForKey(key);

	m_properties->setObject(value, key);
}

void KKNode::setProperty(string key, float newValue) {

	CCString* value = new CCString(floatToString(newValue));

	m_properties->removeObjectForKey(key);

	m_properties->setObject(value, key);

}

void KKNode::setProperty(string key, bool newValue) {
	CCString* value = new CCString(newValue ? "true" : "false");

	m_properties->removeObjectForKey(key);

	m_properties->setObject(value, key);
}

void KKNode::setProperty(string key, const char* newValue) {
	CCString* value = new CCString(newValue);

	m_properties->removeObjectForKey(key);

	m_properties->setObject(value, key);
}

bool KKNode::checkInTapArea(const CCPoint& touchPoint) {

	if (!m_isUseLocalTouch) {
		return contains(touchPoint);
	}

	CCRect boundingBox = CCRectMake(0, 0, m_ccNode->getContentSize().width,
			m_ccNode->getContentSize().height);

	return boundingBox.containsPoint(touchPoint);
}

bool KKNode::contains(KKNode* node) {
	CCNode* ccnode = node->convertToCCNode();
	if (ccnode) {
		CCPoint localPoint = this->convertToCCNode()->convertToNodeSpace(
				ccnode->getParent()->convertToWorldSpace(
						ccnode->getPosition()));

		CCRect boundingBox(0, 0, m_width, m_height);

		return boundingBox.containsPoint(localPoint);
	}

	return false;
}

bool KKNode::contains(const CCPoint& touchPoint) {

	CCRect boundingBox = m_ccNode->boundingBox();

	if (boundingBox.containsPoint(touchPoint)) {

		CCPoint localPoint = getLocalTouchPoint(touchPoint);

		if (m_hasHotArea) {

			assert(this->m_nodeVertexs && this->m_nodeVertexs->count() > 0);

			KKVertexArray* vertexes =
					this->m_nodeVertexs->getObjectAtIndex(0)->getVertexs();

			const KKPoint localPoinInArea(
					localPoint.x - m_ccNode->getContentSize().width / 2,
					localPoint.y - m_ccNode->getContentSize().height / 2);

			return isPointInPoly(*vertexes, localPoinInArea);

		} else {

			boundingBox.origin.x = 0;
			boundingBox.origin.y = 0;
			boundingBox.size.width = m_ccNode->getContentSize().width;
			boundingBox.size.height = m_ccNode->getContentSize().height;

			return boundingBox.containsPoint(localPoint);

		}

	}

	return false;
}

CCPoint KKNode::getLocalTouchPoint(const CCPoint& point) {

	CCPoint localPoint = CCPointApplyAffineTransform(point,
			m_ccNode->parentToNodeTransform());

	return localPoint;
}

bool KKNode::dispatchTouchDown(KKTouch& touch) {

	if (!m_isSupportMultiTouch && getTouchCount() > 0) {
		return true;
	}

	if (KKDirector::isDebug) {
		CCLog(
				"%s dispatchTouchDown viewId=%d,m_isSupportMultiTouch=%d,touchcount=%d \n",
				m_name.c_str(), touch.getViewId(), m_isSupportMultiTouch,
				getTouchCount());
	}

	this->convertToCCNode()->retain();

	KKTouch localTouch(touch, this->getLocalTouchPoint(touch.getPoint()));

	KKNodeArray::CCMutableArrayRevIterator it = m_objects->rbegin();
	KKNodeArray::CCMutableArrayRevIterator end = m_objects->rend();

	KKNode* object = NULL;

	while (it != end) {
		object = (*it);

		//	CCLog("%s check down \n",object->getName().c_str());

		if (object && object->checkTouchable()
				&& object->contains(localTouch.getPoint())) {
			if (object->dispatchTouchDown(localTouch)) {

				this->setInTouch(localTouch.getViewId(), true);

				if (localTouch.getHandled()) {
					break;
				}

			}
		}

		it++;
	}

	if (m_isUseLocalTouch) {
		touch.setHandled(localTouch.getHandled());
	}

	touch.setBubbled(localTouch.getBubbled());

	bool m_isIntouch = this->isInTouch(touch.getViewId());

	if (this->m_isTouchable || m_isIntouch) {

		m_isIntouch = this->onTouchDown(m_isUseLocalTouch ? localTouch : touch)
				|| m_isIntouch;

		this->setInTouch(touch.getViewId(), m_isIntouch);

		if (m_isUseLocalTouch) {
			touch.setBubbled(localTouch.getBubbled());
		}

	}

	return m_isIntouch;
}

void KKNode::dispatchTouchMove(KKTouch& touch) {

//CCLog("%s dispatchTouchMove viewId=%d \n", m_name.c_str(),touch.getViewId());

	KKTouch localTouch(touch, this->getLocalTouchPoint(touch.getPoint()));

	KKNode* object = NULL;

	for (unsigned i = 0; i < m_objects->count(); i++) {
		object = m_objects->getObjectAtIndex(i);

		if (object && object->isInTouch(touch.getViewId())) {
			object->dispatchTouchMove(localTouch);

			/*if (localTouch.getHandled()) {
			 break;
			 }*/
		}
	}

	if (m_isUseLocalTouch) {
		touch.setHandled(localTouch.getHandled());
	}

	touch.setBubbled(localTouch.getBubbled());

	this->onTouchMove(m_isUseLocalTouch ? localTouch : touch);

	if (m_isUseLocalTouch) {
		touch.setBubbled(localTouch.getBubbled());
	}

}

void KKNode::dispatchTouchUp(KKTouch& touch) {

	if (KKDirector::isDebug) {
		CCLog("%s dispatchTouchUp viewId=%d \n", m_name.c_str(),
				touch.getViewId());
	}

	KKTouch localTouch(touch, this->getLocalTouchPoint(touch.getPoint()));

	KKNode* object = NULL;

	for (unsigned i = 0; i < m_objects->count(); i++) {
		object = m_objects->getObjectAtIndex(i);

		if (object && object->isInTouch(touch.getViewId())) {
			object->dispatchTouchUp(localTouch);

			/*if (localTouch.getHandled()) {
			 break;
			 }*/

		}
	}

	if (m_isUseLocalTouch) {
		touch.setHandled(localTouch.getHandled());
	}

	touch.setBubbled(localTouch.getBubbled());

	this->onTouchUp(m_isUseLocalTouch ? localTouch : touch);

	if (m_isUseLocalTouch) {
		touch.setBubbled(localTouch.getBubbled());
	}

	this->setInTouch(touch.getViewId(), false);

	this->convertToCCNode()->release();
}

void KKNode::dispatchTouchCancel(KKTouch& touch) {

	CCLog("%s dispatchTouchCancel viewId=%d \n", m_name.c_str(),
			touch.getViewId());

	KKTouch localTouch(touch, this->getLocalTouchPoint(touch.getPoint()));

	KKNode* object = NULL;

	for (unsigned i = 0; i < m_objects->count(); i++) {
		object = m_objects->getObjectAtIndex(i);

		if (object && object->isInTouch(touch.getViewId())) {
			object->dispatchTouchCancel(localTouch);

			/*if (localTouch.getHandled()) {
			 break;
			 }*/

		}
	}

	this->onTouchCancel(m_isUseLocalTouch ? localTouch : touch);

	this->convertToCCNode()->release();
}

bool KKNode::onTouchDown(KKTouch& touch) {

	m_isMoved = false;

	if (m_GestureDirector) {
		m_GestureDirector->onTouchDown(touch);
	}

	return m_isTouchable;
}

void KKNode::onTouchMove(KKTouch& touch) {

	if (m_GestureDirector) {
		m_GestureDirector->onTouchMove(touch);
	}

}

void KKNode::onTouchUp(KKTouch& touch) {

	if (m_GestureDirector) {
		m_GestureDirector->onTouchUp(touch);
	}

}

void KKNode::onTouchCancel(KKTouch& touch) {

	if (m_GestureDirector) {
		m_GestureDirector->onTouchUp(touch);
	}

}

void KKNode::onScroll(const KKTouch& touch, const CCPoint& scroll) {

//std::cout << getName() << " onScroll " << std::endl;

	if (this->m_isDragable) {
		KKEventActionArgs args;
		args.setTouch(const_cast<KKTouch*>(&touch));
		performEvent("onbeforescroll", &args);

		CCNode* node = dynamic_cast<CCNode*>(this);

		CCPoint prevPoint = touch.getPrevPoint();
		CCPoint point = touch.getPoint();

		if (!m_isUseLocalTouch) {
			prevPoint = node->convertToNodeSpace(touch.getPrevRawPoint());
			point = node->convertToNodeSpace(touch.getRawPoint());
		}

		prevPoint = node->getParent()->convertToNodeSpace(
				touch.getPrevRawPoint());
		point = node->getParent()->convertToNodeSpace(touch.getRawPoint());

		CCPoint scrollRelativeParent = ccpSub(point, prevPoint);

		args.setTouch(const_cast<KKTouch*>(&touch));
		args.setScroll(&scrollRelativeParent);

		args.getTouch()->setBubbled(
				!(this->m_isMovable || this->m_isRotatable || this->m_isZoomable));

		performEvent("onscroll", &args);
	}

}

void KKNode::onTap(const KKTouch& touch) {

//	std::cout << getName() << " onSingleTap " << std::endl;

	KKEventActionArgs args;
	args.setTouch(const_cast<KKTouch*>(&touch));

	if (m_kkParent && m_kkParent->getIsItemTouchable()) {

		KKNode* parent = m_kkParent;

		bool isMoved = false;

		while (parent) {
			if (parent->getIsMoved()) {
				isMoved = true;
				break;
			}
			parent = parent->getKKParent();
		}

		if (!isMoved) {
			args.setData((void*) (this));

			m_kkParent->performEvent("onitemclick", &args);

			if (m_isSoundEffect
					&& KKDirector::shareDirector()->getEnableSoundEffect()) {
				KKAudioManager::sharedAudioManager()->playClickEffect();
			}
		}
	} else {

		KKNode* parent = m_kkParent;

		bool isMoved = false;

		while (parent) {
			if (parent->getIsMoved()) {
				isMoved = true;
				break;
			}
			parent = parent->getKKParent();
		}

		if (!isMoved) {

			performEvent("onclick", &args);

			if (m_isSoundEffect
					&& KKDirector::shareDirector()->getEnableSoundEffect()) {
				KKAudioManager::sharedAudioManager()->playClickEffect();
			}
		}
	}

}

#define SCALE_EFFECT 1.25f

void KKNode::onDown(const KKTouch& touch) {

//	std::cout << getName() << " onDown " << std::endl;

	CCNode* node = dynamic_cast<CCNode*>(this);

	if (node) {
		if (m_clickEffect == KKEFFECT_ZOOMIN) {
			node->setScaleX(node->getScaleX() * SCALE_EFFECT);
			node->setScaleY(node->getScaleY() * SCALE_EFFECT);
		} else if (m_clickEffect == KKEFFECT_ZOOMOUT) {
			node->setScaleX(node->getScaleX() / SCALE_EFFECT);
			node->setScaleY(node->getScaleY() / SCALE_EFFECT);
		} else if (m_clickEffect == KKEFFECT_SHADOW) {
			assert(m_shadowEffectColor != NULL);
			m_shadowEffectColor->setVisible(true);
		}
	}

	KKEventActionArgs args;
	args.setTouch(const_cast<KKTouch*>(&touch));

	performEvent("ondown", &args);

}

void KKNode::onUp(const KKTouch& touch) {

//	std::cout << getName() << " onUp " << std::endl;

	CCNode* node = dynamic_cast<CCNode*>(this);

	if (node) {

		if (m_clickEffect == KKEFFECT_ZOOMIN) {
			node->setScaleX(node->getScaleX() / SCALE_EFFECT);
			node->setScaleY(node->getScaleY() / SCALE_EFFECT);
		} else if (m_clickEffect == KKEFFECT_ZOOMOUT) {
			node->setScaleX(node->getScaleX() * SCALE_EFFECT);
			node->setScaleY(node->getScaleY() * SCALE_EFFECT);
		} else if (m_clickEffect == KKEFFECT_SHADOW) {
			assert(m_shadowEffectColor != NULL);
			m_shadowEffectColor->setVisible(false);
		}
	}

	KKEventActionArgs args;
	args.setTouch(const_cast<KKTouch*>(&touch));

	performEvent("onup", &args);

}

void KKNode::onDrag(const CCPoint& drag) {

	CCNode* node = dynamic_cast<CCNode*>(this);

	KKEventActionArgs args;
	args.setScroll(const_cast<CCPoint*>(&drag));

	if (!performEvent("ondrag", &args)) {
		node->setPosition(drag.x + node->getPositionX(),
				drag.y + node->getPositionY());
	}

}

void KKNode::onZoom(const CCPoint& zoom) {
	CCNode* node = this->convertToCCNode();

	KKEventActionArgs args;
	args.setZoom(const_cast<CCPoint*>(&zoom));

	if (!performEvent("onzoom", &args)) {
		node->setScaleX(node->getScaleX() * zoom.x);
		node->setScaleY(node->getScaleY() * zoom.y);
	}

}

void KKNode::onRotate(const float& angle) {
	CCNode* node = this->convertToCCNode();

	KKEventActionArgs args;
	args.setRotate(angle);

	if (!performEvent("onrotate", &args)) {
		node->setRotation(node->getRotation() + angle);
	}

}

void KKNode::onFling(const KKTouch& touch, const CCPoint& velocity) {
	if (this->m_isDragable) {
		cout << "fling " << m_name << "," << velocity.x << "," << velocity.y
				<< endl;
	}

	KKEventActionArgs args;
	args.setTouch(const_cast<KKTouch*>(&touch));
	args.setVelocity(const_cast<CCPoint*>(&velocity));

	performEvent("onfling", &args);
}

void KKNode::onLongDown(const KKTouch& touch) {

//	std::cout << getName() << " onSingleTap " << std::endl;

	KKEventActionArgs args;
	args.setTouch(const_cast<KKTouch*>(&touch));

	performEvent("onlongdown", &args);

}

void KKNode::onContact(KKNode* contactBody) {
	KKEventActionArgs args;
	args.setData(contactBody);
	performEvent("oncontact", &args);
}

void KKNode::onBeginContact(b2Body* body) {
	KKEventActionArgs args;
	args.setData(body);
	performEvent("onbegincontact", &args);
}
void KKNode::onEndContact(b2Body* body) {
	KKEventActionArgs args;
	args.setData(body);
	performEvent("onendcontact", &args);
}
void KKNode::onPreSolve(b2Body* body) {
	KKEventActionArgs args;
	args.setData(body);
	performEvent("onpresolve", &args);
}
void KKNode::onPostSolve(b2Body* body) {
	KKEventActionArgs args;
	args.setData(body);
	performEvent("onpostsolve", &args);
}

void KKNode::onBeginContact(KKNode* contactBody) {
	KKEventActionArgs args;
	args.setData(contactBody);
	performEvent("onbegincontact", &args);
}
void KKNode::onEndContact(KKNode* contactBody) {
	KKEventActionArgs args;
	args.setData(contactBody);
	performEvent("onendcontact", &args);
}
void KKNode::onPreSolve(KKNode* contactBody) {
	KKEventActionArgs args;
	args.setData(contactBody);
	performEvent("onpresolve", &args);
}
void KKNode::onPostSolve(KKNode* contactBody) {
	KKEventActionArgs args;
	args.setData(contactBody);
	performEvent("onpostsolve", &args);
}

bool KKNode::performEvent(string eventName, KKEventActionArgs* args) {

//cout << m_name << " performEvent " << eventName << endl;

	KKEvent* event = this->m_events->objectForKey(eventName);

	if (event) {

		if (args == NULL) {
			KKEventActionArgs allargs;
			args = &allargs;
		}

		args->setSource(this);

		event->fire(args);

		return true;

	}

	return false;

}

void KKNode::registerEventHandler(string eventName, SEL_CallFuncND eventFunc,
		CCObject* target, bool override) {

	if (!m_events) {
		CCLog("events fail\n");
	}

//CCLog("%s register event=%s\n", m_name.c_str(), eventName.c_str());

	KKEvent* event = this->m_events->objectForKey(eventName);

//CCLog("registerEventHandler success \n");

	if (!event) {
		event = new KKEvent();
		event->setName(eventName);
	} else if (override) {
		event->getActions()->removeAllObjects();
	}

	KKEventHandler* eventHandler = event->getEventHandler();

	if (!eventHandler) {
		eventHandler = new KKEventHandler();
		event->setEventHandler(eventHandler);
	}

	if (target) {
		eventHandler->target = target;
	} else {
		eventHandler->target = dynamic_cast<CCObject*>(this);
	}

	eventHandler->selector = eventFunc;

	this->m_events->setObject(event, eventName);
}

void KKNode::registerEventHandler(string eventName, string handlerName,
		bool override) {

//cout << m_name << " performEvent " << eventName << endl;

	char* funcName = new char[handlerName.length() + 1];

	strcpy(funcName, handlerName.c_str());

	if (override) {
		this->m_events->removeObjectForKey(eventName);
	}

	KKEvent* event = this->m_events->objectForKey(eventName);

	if (!event) {
		event = new KKEvent();
		event->setName(eventName);
	}

	KKEventAction* action = new KKEventAction();

	action->setTarget(this->m_name.c_str());
	action->setTargetId(this->m_id);
	action->setTargetType(TARGET_SPRITE);
	action->setAction(funcName);
	action->setActionType(ACTION_SCRIPT);

	event->getActions()->addObject(action);

	this->m_events->setObject(event, eventName);
}

KKNode* KKNode::findNodeById(int id) {

	KKNode* foundNode = NULL;

	KKNodeArray::CCMutableArrayRevIterator it = m_objects->rbegin();

	KKNode* object = NULL;

	while (it != m_objects->rend()) {
		object = (*it);

		if (object->getId() == id) {
			foundNode = object;
			break;
		} else {
			KKNode* child = object->findNodeById(id);

			if (child) {
				foundNode = child;
				break;
			}
		}

		it++;
	}

	return foundNode;
}

KKNode* KKNode::nodeNamed(string nodeName, bool includeInvisiable) {

	KKNode* foundNode = NULL;

	KKNodeArray::CCMutableArrayRevIterator it = m_objects->rbegin();

	KKNode* object = NULL;

	while (it != m_objects->rend()) {
		object = (*it);

		if (includeInvisiable) {
			object->loadNode();
		}

		if (object->getName() == nodeName) {
			foundNode = object;
			break;
		} else {
			KKNode* child = object->nodeNamed(nodeName, includeInvisiable);

			if (child) {
				foundNode = child;
				break;
			}
		}

		it++;
	}

	return foundNode;
}

KKNode* KKNode::findNodeByProperty(string propertyName, int propertyValue) {

	KKNode* foundNode = NULL;

	KKNodeArray::CCMutableArrayRevIterator it = m_objects->rbegin();

	KKNode* object = NULL;

	while (it != m_objects->rend()) {
		object = (*it);

		if (object->getIntProperty(propertyName) == propertyValue) {
			foundNode = object;
			break;
		}

		it++;
	}

	return foundNode;
}

KKNode* KKNode::findNodeByProperty(string propertyName,
		const char* propertyValue) {

	KKNode* foundNode = NULL;

	KKNodeArray::CCMutableArrayRevIterator it = m_objects->rbegin();

	KKNode* object = NULL;

	while (it != m_objects->rend()) {
		object = (*it);

		if (object->getStringProperty(propertyName) == propertyValue) {
			foundNode = object;
			break;
		}

		it++;
	}

	return foundNode;
}

KKObjectArray* KKNode::findNodesByProperty(string propertyName,
		int propertyValue) {

	KKObjectArray* objects = new KKObjectArray();
	KKNodeArray::CCMutableArrayRevIterator it = m_objects->rbegin();

	KKNode* object = NULL;

	while (it != m_objects->rend()) {
		object = (*it);

		if (object->getIntProperty(propertyName) == propertyValue) {
			objects->push_back(object);
		}

		it++;
	}

	return objects;
}

void KKNode::insertNode(KKNode* node, int zOrder) {

	KKNode* lastNode = m_objects->getLastObject();

	if (lastNode == NULL || lastNode->getZOrder() <= zOrder) {
		m_objects->addObject(node);
	} else {
		unsigned int index = 0;

		KKNodeArray::CCMutableArrayIterator it = m_objects->begin();

		KKNode* object = NULL;

		while (it != m_objects->end()) {
			object = (*it);

			if (object->getZOrder() > zOrder) {
				m_objects->insertObjectAtIndex(node, index);
				break;
			}

			index++;
			it++;
		}
	}

}

void KKNode::reorderNode(KKNode* node, int zOrder) {

	CCAssert(node->getKKParent() || node->getKKParent() == this,
			"can not reorder child.");

	CCNode* ccNode = dynamic_cast<CCNode*>(node);

	if (ccNode) {
		ccNode->retain();
	}

	m_ccNode->reorderChild(ccNode, zOrder);

	m_objects->removeObject(node, false);

	insertNode(node, zOrder);

	node->setZOrder(zOrder);

	if (ccNode) {
		ccNode->release();
	}
}

bool KKNode::addNode(KKNode* node, int zOrder, int tag) {
	CCLog("p:%s,KKNode addNode:%s\n", this->getName().c_str(),node->getName().c_str());
	if (zOrder == 0) {
		zOrder = node->getZOrder();
	} else {
		node->setZOrder(zOrder);
	}

	insertNode(node, zOrder);

	node->m_kkParent = this;

	CCNode* ccNode = dynamic_cast<CCNode*>(node);

	if (ccNode) {

		if (tag == -1) {
			tag = ccNode->getTag();
		}

		if (tag == -1) {
			tag = node->getId();
		}

		this->m_ccNode->addChild(ccNode, zOrder, tag);
	}

	if (node->getIsVisible()) {
		CCRect bounds = ccNode->boundingBox();

		m_minX = min(m_minX, bounds.getMinX());
		m_minY = min(m_minY, bounds.getMinY());

		m_maxX = max(m_maxX, bounds.getMaxX());
		m_maxY = max(m_maxY, bounds.getMaxY());
	}

	this->setIsChildTouchable(
			this->getIsChildTouchable() || node->getIsChildTouchable()
					|| node->getIsTouchable());

	return true;
}

void KKNode::removeNode(KKNode* node, bool cleanup) {

	assert(node);

	node->setKKParent(NULL);

	m_objects->removeObject(node, true);

	CCNode* ccNode = dynamic_cast<CCNode*>(node);

	if (ccNode) {
		this->m_ccNode->removeChild(ccNode, cleanup);
	}

}

void KKNode::removeNodeByTag(int tag, bool cleanup) {

	CCNode* ccNode = m_ccNode->getChildByTag(tag);

	if (ccNode) {

		KKNode* node = dynamic_cast<KKNode*>(ccNode);

		if (node) {

			node->setKKParent(NULL);

			m_objects->removeObject(node, cleanup);
		}

		this->m_ccNode->removeChild(ccNode, cleanup);

	}

}

void KKNode::removeAllNodes(bool cleanup) {

	KKNode* kknode = NULL;
	KKNODE_FOREACH(m_objects,kknode){
	kknode->setKKParent(NULL);
}

	this->m_objects->removeAllObjects();
	this->m_ccNode->removeAllChildrenWithCleanup(cleanup);
	CCTextureCache::sharedTextureCache()->removeUnusedTextures();
}

CCSize KKNode::measureInnerSize() {
	m_minX = 0;
	m_minY = 0;
	m_maxX = m_width;
	m_maxY = m_height;

	CCRect bounds;

	CCNode* child = NULL;
	KKNode* kknode = NULL;
	KKNODE_FOREACH(m_objects,kknode){
	child = dynamic_cast<CCNode*> (kknode);
	if (child) {

		bounds = child->boundingBox();

		m_minX = min(m_minX, bounds.getMinX());
		m_minY = min(m_minY, bounds.getMinY());

		m_maxX = max(m_maxX, bounds.getMaxX());
		m_maxY = max(m_maxY, bounds.getMaxY());
	}
}

	return CCSizeMake(m_maxX - m_minX, m_maxY - m_minY);
}

void KKNode::resize(const float& width, const float& height) {

	this->m_width = width;
	this->m_height = height;

	m_maxX = this->m_width;
	m_maxY = this->m_height;

	measureInnerSize();

	CCNode* node = dynamic_cast<CCNode*>(this);

	CCTextureProtocol* texture = dynamic_cast<CCTextureProtocol*>(this);

	if (!texture) {
		node->setContentSize(CCSize(this->m_width, this->m_height));
	}

	if (node->getScaleX() > 0) {
		node->setScaleX(this->m_width / node->getContentSize().width);
	} else {
		node->setScaleX(-this->m_width / node->getContentSize().width);
	}

	if (node->getScaleY() > 0) {
		node->setScaleY(this->m_height / node->getContentSize().height);
	} else {
		node->setScaleY(-this->m_height / node->getContentSize().height);
	}

	if (m_bgColor) {
		m_bgColor->setContentSize(CCSizeMake(this->m_width, this->m_height));
	}

	if (m_shadowEffectColor) {
		m_shadowEffectColor->setContentSize(
		CCSizeMake(this->m_width, this->m_height));
	}

	measure();
	layout();
}

void KKNode::measure() {
	if (m_layout) {
		m_layout->measure(this, this->m_objects);
	}
}

void KKNode::layout() {
	if (m_layout) {
		m_layout->layout(this, this->m_objects);
	}
}

KKNodeParser* KKNodeParser::m_defaultParser = new KKDefaultParser();
KKDictionary<string, KKNodeParser*> KKNodeParser::m_parsers;

KKNodeParser* KKNodeParser::getParser(TiXmlElement* element) {

	const char* component = element->Attribute("component");

	KKNodeParser* parser = NULL;

	if (component) {
		parser = m_parsers.objectForKey(component);
	}

	if (!parser) {
		parser = m_parsers.objectForKey(element->Attribute("class"));
	}

	if (!parser) {
		parser = m_defaultParser;
		CCLog("no parse found to component=%s\n", component);
	}

	return parser;

}

KKNode* KKNodeParser::parseFromXml(TiXmlElement* element, KKNode* parent) {
	KKNodeParser* parser = NULL;

	const char* path = element->Attribute("path");

	TiXmlDocument *myDocument = NULL;

	if (path) {
		myDocument = XmlUtils::readXML(path);
		element = myDocument->RootElement();
	}

	parser = getParser(element);

	KKNode* node = parser->parse(element, parent);

	if (node) {
		node->setTiXmlDocument(myDocument);
	} else {
		CC_SAFE_DELETE(myDocument);
	}

	return node;

}
